/**
 * @file 场景窗口实现
 *
 * 场景窗口实现
 *
 * @author wq1977@gmail.com
 */

//#include <wx/html/htmlwin.h>
#include "ScenariosForm.h"
#include "app.h"
#include "wx/splitter.h"

extern const wxEventType wxEVT_SCENARIO_EXIT;
extern const wxEventType wxEVT_SCENARIO_UPDATE;


IMPLEMENT_DYNAMIC_CLASS(ScenariosForm, wxMDIChildFrame)

BEGIN_EVENT_TABLE(ScenariosForm, wxMDIChildFrame)
    EVT_TEXT(SF_TERMNUM, ScenariosForm::OnTermNumChange)
    EVT_BUTTON(CMENU_DO_START, ScenariosForm::OnDoStart)
    EVT_BUTTON(CMENU_DO_STOP, ScenariosForm::OnDoStop)
    EVT_BUTTON(CMENU_CONF_SCEN, ScenariosForm::OnDoScenConf)
    EVT_BUTTON(CMENU_DO_REPORT, ScenariosForm::OnDoReport)
    EVT_MENU(CMENU_START_TRACE,ScenariosForm::OnStartTrace)
    EVT_CUSTOM(wxEVT_SCENARIO_EXIT,-1,ScenariosForm::OnScenarioExit)
    EVT_CUSTOM(wxEVT_SCENARIO_UPDATE,-1,ScenariosForm::OnScenarioUpdate)
    EVT_CLOSE(ScenariosForm::OnClose)
    EVT_RADIOBOX(CMENU_CASE_STYLE, ScenariosForm::OnCaseStyleChange)
    EVT_TIMER(101, ScenariosForm::OnTimer)
END_EVENT_TABLE()

/*class ShowHtmlDialog : public wxDialog
{
public:
  ShowHtmlDialog(wxWindow *parent, const wxString& path);
};


ShowHtmlDialog::ShowHtmlDialog(wxWindow *parent, const wxString& path)
             : wxDialog(parent, -1, wxString(_T("Modal dialog")))
{
    wxBoxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);

    wxButton *btnOk = new wxButton(this, wxID_CANCEL, _T("&Close"));
    wxHtmlWindow*html = new wxHtmlWindow(this);
    html->LoadPage(path);
    sizerTop->Add(html, 0, wxALIGN_CENTER | wxALL, 5);
    sizerTop->Add(btnOk, 0, wxALIGN_CENTER | wxALL, 5);

    SetAutoLayout(TRUE);
    SetSizer(sizerTop);

    sizerTop->SetSizeHints(this);
    sizerTop->Fit(this);

}*/


void ScenariosForm::OnCaseStyleChange(wxCommandEvent& event){
  m_ScenariosControlPanel->LockControl(true);
}

void ScenariosForm::OnClose(wxCloseEvent& event){
	if (m_ScenarioControl) {
		wxCommandEvent nouse;
		OnDoStop(nouse);
	}

	wxNode *node = Tracers.GetFirst();
	while (node)
	{
		TraceForm *win = (TraceForm *)node->GetData();
		win->SetTraceSource(NULL);
		node = node->GetNext();
	}
	event.Skip();
}

void ScenariosForm::OnStartTrace(wxCommandEvent& event){
	if (!m_ScenarioControl){
	    TraceForm *subframe = new TraceForm(wxGetApp().frame, _("Trace Form"),
                                    wxPoint(-1, -1), wxSize(-1, -1),
                                    wxDEFAULT_FRAME_STYLE);

		subframe->SetTraceSource(this);
		for (int i=0;i<m_TerminalStateGrid->GetNumberCols();i++){
			for (int j=0;j<m_TerminalStateGrid->GetNumberRows();j++){
				if (m_TerminalStateGrid->IsInSelection(j,i)){
					int TermIndex=j*m_TerminalStateGrid->GetNumberCols()+i;
					subframe->AppendTraceTarget(TermIndex);
				}
			}
		}
		AppendTracer(subframe);
    	subframe->Show(TRUE);
	//wxGetApp().frame->Tile();
	}
}

void ScenariosForm::OnScenarioUpdate(wxEvent& event){
    //if (m_ScenarioControl){
    //m_ScenariosResultGrid->UpdateState();
    //}
}

void ScenariosForm::OnScenarioExit(wxEvent& event){
	TRACE(TL_MESSAGE,_("Recv ScenarioExit Event!!"));
	wxCommandEvent nouse;
	OnDoStop(nouse);
}

void ScenariosForm::OnDoScenConf(wxCommandEvent& event){
	int ScenariosIndex = m_ScenariosControlPanel->GetSelectScenariosIndex();
	if (ScenariosIndex<0){
		wxLogError(_("Before start, you should select one scenarios to run!"));
		return;
	}
	else if (ScenariosIndex>(int)wxGetApp().m_ScenariosManager->AllScenarios.size()){
		wxLogError(_("This should never happen,restart the program,if it is still happen,contact the author!"));
		return;
	}

    ConfigDialog m_dialog(this,wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex]->GetMap());
	m_dialog.ShowModal();
}

void ScenariosForm::OnDoStop(wxCommandEvent& event){
    if (m_ScenariosControlPanel->IsSafeStop()){
	if (m_ScenarioControl){
	    if (!m_ScenarioControl->SetSafeStop()) //Wait pendding case finish!
		return;
	}
    }

	m_ScenariosResultGrid->UpdateState();
    m_ScenariosControlPanel->LockControl(true);

    if (m_ScenarioControl) {
	m_ScenarioControl->Quit();
	delete(m_ScenarioControl);
	m_ScenarioControl=NULL;
    }

    //TOREMOVE
    //wxDebugContext::PrintStatistics();

    wxGetApp().CancelScenarioTimer(FormIndex);
    //wxDebugContext::Dump();

    //wxDebugContext::PrintStatistics();
    //wxDebugContext::Dump();

    wxDateTime now = wxDateTime::UNow();
    TRACE(TL_MESSAGE,wxString::Format(_("Scenarios Stop at %d-%d-%d %d:%d:%d %d"),
				      now.GetYear(),
				      now.GetMonth()+1,
				      now.GetDay(),
				      now.GetHour(),
				      now.GetMinute(),
				      now.GetSecond(),
				      now.GetMillisecond()));
    //wxGetApp().IncStatisticItem(STT_OSIP_CURRENT_TRANS_NUM);
    TRACE(TL_MESSAGE,(now.Subtract(ScenarioStartAt)).Format(_("Scenarios last %D day(s) %H hour(s) %M minute(s) %S second(s) %l millisecond(s)")));

}

void ScenariosForm::OnDoReport(wxCommandEvent& event){
    //Dump all the transaction in the Current Stack.
    /*
    osip_transaction_t *transaction;
    osip_list_iterator_t iterator;
    osip_list_t * alllist[4]={
	wxGetApp().osip->osip_ict_transactions,
	wxGetApp().osip->osip_ist_transactions,
	wxGetApp().osip->osip_nict_transactions,
	wxGetApp().osip->osip_nist_transactions
    };
    for (int i=0;i<4;i++){
	int len;
	len = osip_list_size (alllist[i]);
	if ( len > 0){
	    wxGetApp().DoLog(wxString::Format(wxT("Transaction Type:%d\n"),i));;
	    transaction =
		(osip_transaction_t *) osip_list_get_first (alllist[i],  &iterator);
	    while (osip_list_iterator_has_elem (iterator))  {
		char *msgP;
		size_t msgLen;
		int j;
		if((j = osip_message_to_str(transaction->orig_request, &msgP, &msgLen)) != 0){
		    wxGetApp().DoLog(_("failed to convert message\n"));
		    continue;
		}
		wxGetApp().DoLog(wxString::Format(wxString(wxT("[]"))+_("[Total Len:%d]:\n%s"),msgLen, STT_LStr(msgP)));
		osip_free(msgP);
		transaction = (osip_transaction_t *) osip_list_get_next (&iterator);
	    }
	}
    }

    */

  if (m_ScenarioControl){
    m_ScenarioControl->DoReport();
  }
  if (!LastReportPath.IsEmpty()){

      /*wxString url = LastReportPath;
      bool ok = false;
      wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("html"));
      if ( ft ){
	  wxString cmd;
	  ok = ft->GetOpenCommand(&cmd,
				  wxFileType::MessageParameters(url, wxEmptyString));
	  delete ft;

	  if (ok)
	      {
		  ok = (wxExecute(cmd, wxEXEC_ASYNC) != 0);
	      }
	      }*/

#ifdef WIN32
      ShellExecute(NULL, wxT("open"), LastReportPath.c_str(), wxT(""), NULL, SW_SHOWNORMAL);
#else
      wxString cmd=wxT("firefox file://");
      cmd+=LastReportPath;
      wxExecute(cmd);
#endif
  }
}

void ScenariosForm::OnDoStart(wxCommandEvent& event){

  int CaseStyle=m_ScenariosControlPanel->GetCaseStyle();
  int MaxTermNeeded=0;
  int ScenariosIndex=-1;
  if (CaseStyle==0){ //Fixed Case
    ScenariosIndex = m_ScenariosControlPanel->GetSelectScenariosIndex();
    if (ScenariosIndex<0){
      wxLogError(_("Before start, you should select one scenarios to run!"));
      return;
    }
    else if (ScenariosIndex>(int)wxGetApp().m_ScenariosManager->AllScenarios.size()){
      wxLogError(_("This should never happen,restart the program,if it is still happen,contact the author!"));
      return;
    }

    if (wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex]->IsSourceModified()){
      wxMessageDialog dialog(NULL, _("The Case Source has been modified,make sure there is no scenario is running and press return!"),
			     _("Alert"), wxOK|wxCANCEL|wxICON_INFORMATION);

      if (dialog.ShowModal()==wxID_OK){
	wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex]->ReLoad();
      }
      else{
	return;
      }
    }

    if (wxGetApp().m_ScenariosManager->DefaultScenario->IsSourceModified()){
      wxMessageDialog dialog(NULL, _("The Default Case Source has been modified,make sure there is no scenario is running and press return!"),
			     _("Alert"), wxOK|wxCANCEL|wxICON_INFORMATION);

      if (dialog.ShowModal()==wxID_OK){
	wxGetApp().m_ScenariosManager->DefaultScenario->ReLoad();
      }
      else{
	return;
      }
    }
    MaxTermNeeded=wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex]->GetTermNumNeeded();
  }
  else{
    MaxTermNeeded=wxGetApp().m_ScenariosManager->GetMaxTermNeeded();
  }

  int TermNum=m_ScenariosControlPanel->GetTermNum();
  int TestTimes=m_ScenariosControlPanel->GetCallTimes();
  if (CaseStyle==1) TestTimes=wxGetApp().m_ScenariosManager->AllScenarios.size();
  if (TermNum<0){
    wxLogError(_("The Terminal nums what you filled maybe incorrect,Check it!"));
    return;
  }
  else if (TermNum>MAX_TERM_NUM){
    wxLogError(_("The Terminal nums what you filled is too much,Check it!"));
    return;
  }
  else if (TermNum<MaxTermNeeded){
    wxLogError(wxString::Format(_("To Run this case, you need at least %d Term!"),MaxTermNeeded));
    return;
  }

  m_ScenariosControlPanel->LockControl();
  if (m_ScenarioControl) {
    delete(m_ScenarioControl);
  }
  ScenarioStartAt = wxDateTime::UNow();
  m_TerminalStateGrid->InitTerms(TermNum);

  //TOREMOVE
  //wxDebugContext::SetCheckpoint();

  SetTitle(wxString::Format(wxString(_("Scenarios Form %d"))+wxT(" ")+_("Start at:%d-%d-%d %d:%d:%d"),
			    SeqId,
				      ScenarioStartAt.GetYear(),
				      ScenarioStartAt.GetMonth()+1,
				      ScenarioStartAt.GetDay(),
				      ScenarioStartAt.GetHour(),
				      ScenarioStartAt.GetMinute(),
				      ScenarioStartAt.GetSecond()));
  //wxDebugContext::Dump();

  if (CaseStyle==0){
    TRACE(TL_MESSAGE,wxString::Format(_("Scenarios [%s] Start at %d-%d-%d %d:%d:%d %d"),
				      wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex]->filename.c_str(),
				      ScenarioStartAt.GetYear(),
				      ScenarioStartAt.GetMonth()+1,
				      ScenarioStartAt.GetDay(),
				      ScenarioStartAt.GetHour(),
				      ScenarioStartAt.GetMinute(),
				      ScenarioStartAt.GetSecond(),
				      ScenarioStartAt.GetMillisecond()));

    m_ScenarioControl = new SttScenarioControl(this,wxGetApp().m_ScenariosManager->AllScenarios[ScenariosIndex],
					       TermNum,TestTimes,
					       m_ScenariosControlPanel->GetCallDuration(),
					       m_ScenariosControlPanel->GetCallHold(),
					       m_ScenariosControlPanel->GetHeavy(),
					       m_ScenariosControlPanel->GetFinalRuleStyle());
  }
  else{
    wxString choices[] =
      {
	_("Fixed Case Test"),
	_("Round Case Test"),
	_("Random Case Test"),
      };

    TRACE(TL_MESSAGE,wxString::Format(_("Test Style [%s] Start at %d-%d-%d %d:%d:%d %d"),
				      choices[CaseStyle].c_str(),
				      ScenarioStartAt.GetYear(),
				      ScenarioStartAt.GetMonth()+1,
				      ScenarioStartAt.GetDay(),
				      ScenarioStartAt.GetHour(),
				      ScenarioStartAt.GetMinute(),
				      ScenarioStartAt.GetSecond(),
				      ScenarioStartAt.GetMillisecond()));

    m_ScenarioControl = new SttScenarioControl(this,CaseStyle,
					       TermNum,TestTimes,
					       m_ScenariosControlPanel->GetCallDuration(),
					       m_ScenariosControlPanel->GetCallHold(),
					       m_ScenariosControlPanel->GetHeavy(),
					       m_ScenariosControlPanel->GetFinalRuleStyle());
  }
}

void ScenariosForm::OnTermNumChange(wxCommandEvent& event){
	wxString Value=event.GetString();
	long TermNum=DEFAULT_TERM_NUM;
	if (!Value.IsEmpty()){
		Value.ToLong(&TermNum);
	}

	if (TermNum>MAX_TERM_NUM){
	  wxLogError(wxString::Format(_("The Value should be not more than %d!"),MAX_TERM_NUM));
	  return;
	}
	m_TerminalStateGrid->InitTerms(TermNum);
}

TermControl *ScenariosForm::GetTermCtrl(int Index){
	if (!m_ScenarioControl) return NULL;
	return m_ScenarioControl->GetTermCtrl(Index);
}

ScenariosForm::ScenariosForm(int Seq, wxMDIParentFrame *parent, const wxString& title,
                 const wxPoint& pos, const wxSize& size,
                 const long style)
       : wxMDIChildFrame(parent, -1, title, pos, size,
                         style | wxNO_FULL_REPAINT_ON_RESIZE),
	 m_timer(this,101)
{
	SeqId = Seq;
	LastReportPath=wxT("");
	Daemon=wxT("");
	m_ScenarioControl=NULL;

	wxBoxSizer *sizerHor = new wxBoxSizer(wxHORIZONTAL);
    wxSplitterWindow* m_splitter = new wxSplitterWindow(this);
    m_splitter->SetSashGravity(0);

	wxPanel *panelright = new wxPanel(m_splitter);
	wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);

	m_TerminalStateGrid = new TerminalStateGrid( panelright,
						     -1,
						     wxPoint( 0, 0 ));

	m_ScenariosResultGrid = new ScenariosResultGrid( panelright,
							 -1,
							 wxPoint( 0, 0 ));

	sizerRight->Add(m_TerminalStateGrid,1,wxEXPAND | wxALL,0);
	sizerRight->Add(m_ScenariosResultGrid,0,wxEXPAND | wxALL,0);

	m_ScenariosControlPanel = new ScenariosControlPanel(m_splitter, -1,wxPoint( 0, 0 ));
	m_ScenariosControlPanel->LockControl(true);

	m_timer.Start(5000);

	//sizerHor->Add(m_ScenariosControlPanel,0,wxEXPAND | wxALL,0);
	sizerHor->Add(m_splitter,1,wxEXPAND | wxALL,0);
	panelright->SetSizer(sizerRight);
	panelright->SetAutoLayout(TRUE);
	m_splitter->SplitVertically(m_ScenariosControlPanel, panelright, m_ScenariosControlPanel->GetMinWidth());
	SetAutoLayout(TRUE);
	SetSizer(sizerHor);

}

ScenariosForm::~ScenariosForm()
{
	if (m_ScenarioControl){
		delete(m_ScenarioControl);
		m_ScenarioControl=NULL;
	}
	wxGetApp().EraseFormIndex(this,FormIndex);
}

const wxCharBuffer ConvertToUTF8(wxString anyString)
{
    return wxConvUTF8.cWC2MB( anyString.wc_str(*wxConvCurrent) ) ;
}



void ScenariosForm::OnTimer(wxTimerEvent& event){
    if (m_ScenarioControl){
	m_ScenariosResultGrid->UpdateState();
    }
    if (!Daemon.IsEmpty()){
	stClient* client = new stClient;
	wxString hostName = wxT("localhost");
	wxConnectionBase* connection =
	    client->MakeConnection(hostName,
				   Daemon, wxT("Daemon"));
        if (connection) {
	  wxString param=wxString::Format(wxT("update|%d|%d|%d"),RunningScenariosNum,SuccScenariosNum,FailScenariosNum);
	  const wxCharBuffer bUTF8 = ConvertToUTF8(param);
	  const char*pchar=bUTF8;
	  connection->Execute((const wxChar*)pchar,strlen(pchar));
	    connection->Disconnect();
	    delete connection;
	}
        else   {
	    wxLogStatus(_("the Daemon instance may be too busy too respond."));
	}
        delete client;
    }
}
